package dataserver;

import java.io.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.net.ssl.SSLSocket;

import com.mysql.jdbc.UpdatableResultSet;

public class Worker extends Thread {

	private SSLConnection sslClient;
	private DataBase database;


	public Worker(SSLConnection sslClient) {
		this.sslClient = sslClient;
		this.database = new DataBase("seokje.iptime.org:3306", "hie database", "hie", "hie");
	}

	public void run() {
		Message message = null;
		System.out.println("thread created");
		try {		
			message = new Message(sslClient.readLine());
			if (message != null) { 
				System.out.println("message = " + message.toXml());
				if (message.getMessage().equals("requestHealthRecord")) {

					loadHealthRecord(message);
				}
				else if (message.getMessage().equals("createHealthRecord")) {
					createHealthRecord(message);
				}
				else if (message.getMessage().equals("alterHealthRecord")) {
					System.out.println("alter health record");
					alterHealthRecord(message);
				}
				else if (message.getMessage().equals("alterAccessControlList")) {
					alterAccessControlList(message);
				}
				else if (message.getMessage().equals("requestAccessControlList")) {
					loadAccessControlList(message);
				}
				else if (message.getMessage().equals("cacheHealthRecord")) {
					cacheHealthRecord(message);
				}
				else if (message.getMessage().equals("loadAllHealthRecord")) {
					loadAllPublicHealthRecord(message);
				}
			}
		} catch (Exception e) {
			;
		}
		try {
			sslClient.close();
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		System.out.println("thread closed");
	}

	private void alterAccessControlList(Message message) throws IOException {
		String patientId = message.getHealthRecordAttribute("id");
		String acl = message.getHealthRecordAttribute("acl");
		System.out.println("alter health record");
		try {
			database.connect();
			database.connection.setAutoCommit(false);
			database.preparedStatement = database.connection.prepareStatement("update healthrecord set acl=? where id=?");
			database.preparedStatement.setString(1, acl);
			database.preparedStatement.setString(2, patientId);
			database.preparedStatement.executeUpdate();
			database.connection.commit();	
			System.out.println("health record (acl) for " + patientId + " updated");
			sslClient.writeLine(new Message().setMessage("updated").toXml());
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			sslClient.writeLine(new Message().setMessage("failed").toXml());
		} finally {
			try {
				database.preparedStatement.close();
				database.connection.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}		
	}

	
	private void alterHealthRecord(Message message) throws IOException {
		String patientId = message.getHealthRecordAttribute("id");
		String privateRecord = message.getHealthRecordAttribute("private");
		String publicRecord = message.getHealthRecordAttribute("public");
		System.out.println("alter health record");
		System.out.println(patientId);
		System.out.println(privateRecord);
		System.out.println(publicRecord);
		
		try {
			database.connect();
			database.connection.setAutoCommit(false);
			database.preparedStatement = database.connection.prepareStatement("update healthrecord set private=?, public=?, updated=? where id=?");
			database.preparedStatement.setString(1, privateRecord);
			database.preparedStatement.setString(2, publicRecord);
			database.preparedStatement.setInt(3, 2);
			database.preparedStatement.setString(4, patientId);
			database.preparedStatement.executeUpdate();
			database.connection.commit();	
			System.out.println("health record for " + patientId + " updated");
			sslClient.writeLine(new Message().setMessage("updated").toXml());

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			sslClient.writeLine(new Message().setMessage("failed").toXml());
		} finally {
			try {
				database.preparedStatement.close();
				database.connection.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}		
	}

	private void loadAccessControlList(Message message) throws IOException {
		String patientId = message.getHealthRecordAttribute("id");
		try {
			database.connect();
			database.connection.setAutoCommit(false);
			database.preparedStatement = database.connection.prepareStatement("select * from healthrecord where id = ?");
			database.preparedStatement.setString(1, patientId);
			database.resultSet = database.preparedStatement.executeQuery();
			if (database.resultSet.next()) {
				sslClient.writeLine(new Message().setMessage("found")
						.setHealthRecord(null, null, null, database.resultSet.getString("acl"), null, null)
						.toXml());
			}
			else {
				sslClient.writeLine(new Message().setMessage("failed").toXml());
			}
			database.close();

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			;
		}

	}

	private void cacheHealthRecord(Message message) throws IOException {
		try {
			database.connect();
			database.connection.setAutoCommit(false);
			database.preparedStatement = database.connection.prepareStatement("select public, identifier  from healthrecord where updated = ?");
			database.preparedStatement.setString(1, "updated");
			database.resultSet = database.preparedStatement.executeQuery();
			while (database.resultSet.next()) {
				int i = database.resultSet.getInt("identifier");
				sslClient.writeLine(new Message().setMessage("found")
						.setHealthRecord(null, null, database.resultSet.getString("public"), null, null, Integer.toString(i))
						.toXml());
			}
			sslClient.writeLine(new Message().setMessage("end").toXml());
			
			database.preparedStatement.close();
			
			database.preparedStatement = database.connection.prepareStatement("update healthrecord set updated=? where updated=?");
			database.preparedStatement.setString(1, "updated");
			database.preparedStatement.setString(2, "clean");
			database.preparedStatement.executeUpdate();
			database.connection.commit();	
			
			database.preparedStatement.close();			
			database.connection.close();
			
		} catch (SQLException e) {
			try {
				sslClient.writeLine(new Message().setMessage("failed").toXml());
			} catch (IOException e1) {
				;
			}	
		} 	
	}
	
	private void loadAllPublicHealthRecord(Message message) throws IOException {
		try {
			database.connect();
			database.connection.setAutoCommit(false);
			database.preparedStatement = database.connection.prepareStatement("select public, identifier  from healthrecord");
			database.resultSet = database.preparedStatement.executeQuery();
			while (database.resultSet.next()) {
				int i = database.resultSet.getInt("identifier");
				sslClient.writeLine(new Message().setMessage("found")
						.setHealthRecord(null, null, database.resultSet.getString("public"), null, null, Integer.toString(i))
						.toXml());
			}
			sslClient.writeLine(new Message().setMessage("end").toXml());
			
			database.preparedStatement.close();	
			database.connection.close();
			
		} catch (SQLException e) {
			try {
				sslClient.writeLine(new Message().setMessage("failed").toXml());
			} catch (IOException e1) {
				;
			}	
		} 	
	}
	
	private void loadHealthRecord(Message message) throws IOException {
		String requestId = message.getHealthRecordAttribute("id");
		try {
			database.connect();
			database.connection.setAutoCommit(false);
			database.preparedStatement = database.connection.prepareStatement("select * from healthrecord where id = ?");
			database.preparedStatement.setString(1, requestId);
			database.resultSet = database.preparedStatement.executeQuery();
			if (database.resultSet.next()) {
				int i = database.resultSet.getInt("identifier");
				
				sslClient.writeLine(new Message().setMessage("found")
						.setHealthRecord(database.resultSet.getString("id"), database.resultSet.getString("private"), database.resultSet.getString("public"), database.resultSet.getString("acl"), database.resultSet.getString("doctor"), Integer.toString(i))
						.toXml());
			}
			else {
				sslClient.writeLine(new Message().setMessage("failed").toXml());
			}
			database.close();

		} catch (SQLException e) {
			try {
				sslClient.writeLine(new Message().setMessage("failed").toXml());
			} catch (IOException e1) {
				;
			}
		}
	}

	private int countHealthRecord() {
		int count = -1;
		try {
			
			database.connect();
			database.connection.setAutoCommit(false);
			database.preparedStatement = database.connection.prepareStatement("select count(*) from healthrecord");
			database.resultSet = database.preparedStatement.executeQuery();
			if (database.resultSet.next()) {
				count = database.resultSet.getInt(1);
			}
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			
		} finally {
			try {
				database.preparedStatement.close();
				database.connection.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return count;		
	}
	
	private void createHealthRecord(Message message) throws IOException {
		
		String doctorId = message.getIdentityAttribute("id");
		String patientId = message.getHealthRecordAttribute("id");
		String privateRecord = message.getHealthRecordAttribute("private");
		String publicRecord = message.getHealthRecordAttribute("public");
		String acl = message.getHealthRecordAttribute("acl");
		
		try {
			int i = countHealthRecord();
			System.out.println("num rec = " + i);
			database.connect();
			database.connection.setAutoCommit(false);
			database.preparedStatement = database.connection.prepareStatement("insert into healthrecord(id, doctor, private, public, acl, updated, identifier) values (?, ?, ?, ?, ?, ?, ?)");
			database.preparedStatement.setString(1, patientId);
			database.preparedStatement.setString(2, doctorId);
			database.preparedStatement.setString(3, privateRecord);
			database.preparedStatement.setString(4, publicRecord);
			database.preparedStatement.setString(5, acl);
			database.preparedStatement.setString(6, "updated");
			database.preparedStatement.setInt(7, i);
			database.preparedStatement.executeUpdate();
			database.connection.commit();
			sslClient.writeLine(new Message().setMessage("created").setHealthRecord(null, null, null, null, null, Integer.toString(i)).toXml());
			System.out.println("new health record for " + patientId + " stored");			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			sslClient.writeLine(new Message().setMessage("failed").toXml());	 
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				database.preparedStatement.close();
				database.connection.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}
